package org.example.ws;

import com.sage.toolkit.gson.GsonUtils;
import lombok.SneakyThrows;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketMessage;
import org.springframework.web.socket.WebSocketSession;

import java.util.LinkedHashSet;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;

public class ChatRoom {
    public static final ChatRoom EMPTY = new ChatRoom(null);
    private final Object id;
    private final Set<WebSocketSession> sessionSet;
    private final WebSocketSession ignoreSession;

    public ChatRoom(Object id) {
        this(id, new LinkedHashSet<>(), null);
    }

    private ChatRoom(Object id, Set<WebSocketSession> sessionSet, WebSocketSession ignoreSession) {
        this.id = id;
        this.sessionSet = sessionSet;
        this.ignoreSession = ignoreSession;
    }

    public int sessionCount() {
        return sessionSet.size();
    }

    public boolean addSession(WebSocketSession session) {
        return sessionSet.add(session);
    }

    public boolean removeSession(WebSocketSession session) {
        return sessionSet.remove(session);
    }

    public <T> Set<T> convertSessionSet(Function<WebSocketSession, T> mapper) {
        return sessionSet.stream()
                .filter(session -> !session.equals(ignoreSession))
                .map(mapper)
                .collect(Collectors.toCollection(LinkedHashSet::new));
    }

    @SneakyThrows
    public <T> void emit(WebSocketMessage<T> message) {
        Set<WebSocketSession> sessionSet = this.convertSessionSet(Function.identity());
        for (WebSocketSession session : sessionSet) {
            session.sendMessage(message);
        }
    }

    public void emit(Object... args) {
        String payload = GsonUtils.toJson(args);
        this.emit(new TextMessage(payload));
    }

    protected ChatRoom ignore(WebSocketSession session) {
        return new ChatRoom(id, sessionSet, session);
    }
}
